Skip to content

fix(reporting): reconcile program_completion_days sign and dual definitions#2416

Open
blarghmatey wants to merge 1 commit into
mainfrom
worktree-program-completion-days-consolidate
Open

fix(reporting): reconcile program_completion_days sign and dual definitions#2416
blarghmatey wants to merge 1 commit into
mainfrom
worktree-program-completion-days-consolidate

Conversation

@blarghmatey

Copy link
Copy Markdown
Member

What

Two competing definitions of the same metric under near-identical names:

Fix

  • Swapped the date_diff operands in the mart so program_completion_days is certificate-minus-start (positive), matching both models' documented description ("days between first course start and program completion").
  • program_enrollment_with_user_report now selects enrollment_detail.program_completion_days directly instead of re-deriving it, and dropped the now-unused first_courserun_start_on_date aggregate from courses_detail.

Part of #2375 (2026-07 dbt warehouse audit).

Closes #2387

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 9, 2026 17:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR resolves a metric correctness/consistency problem in the dbt warehouse by fixing the sign of program_completion_days at the source mart layer and removing a redundant, independently-derived definition in the reporting layer.

Changes:

  • Corrected marts__combined_program_enrollment_detail.program_completion_days to compute certificate date minus first course start date (positive day counts).
  • Updated program_enrollment_with_user_report to source program_complete_days directly from the mart’s program_completion_days, and removed the no-longer-needed first_courserun_start_on_date aggregate from the report’s courses_detail CTE.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/ol_dbt/models/marts/combined/marts__combined_program_enrollment_detail.sql Fixes the date_diff operand order so program_completion_days matches the documented metric semantics.
src/ol_dbt/models/reporting/program_enrollment_with_user_report.sql Eliminates a duplicate metric derivation by selecting program_completion_days from the upstream mart and dropping the unused supporting aggregate.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@blarghmatey blarghmatey force-pushed the worktree-program-completion-days-consolidate branch from 90c6157 to f6e4e9b Compare July 11, 2026 00:55
Comment on lines 91 to 97
combined_users.user_address_postal_code, combined_users2.user_address_postal_code
) as user_address_postal_code
, case when courses_detail.capstone_sum > 0 then 'Y' else 'N' end as capstone_ind
, date_diff(
'day'
, courses_detail.first_courserun_start_on_date
, cast(substring(enrollment_detail.programcertificate_created_on, 1, 10) as date)
) as program_complete_days
, enrollment_detail.program_completion_days as program_complete_days
from enrollment_detail
left join combined_users
on enrollment_detail.platform_name = '{{ var("edxorg") }}'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The calculation for first_courserun_start_on_date now incorrectly includes unverified enrollments, which alters the program_completion_days metric by using an earlier start date for some users.
Severity: MEDIUM

Suggested Fix

The reporting model should revert to its previous logic for calculating first_courserun_start_on_date. Instead of consuming the field from the mart, re-implement the logic that filters for courserunenrollment_enrollment_mode = 'verified' when determining the minimum course run start date. This will restore the original definition of the program_completion_days metric.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/ol_dbt/models/reporting/program_enrollment_with_user_report.sql#L91-L97

Potential issue: The reporting model `program_enrollment_with_user_report.sql` now
sources the `first_courserun_start_on_date` from a mart model. The previous
implementation calculated this date using only 'verified' enrollments. The mart model,
however, calculates this date based on all enrollment types, including unverified ones.
This change in logic means that for any user with an unverified enrollment that started
before their first verified one, the `program_completion_days` metric will be calculated
from this earlier date, leading to a significant and unintended change in the report's
output.

Did we get this right? 👍 / 👎 to inform future reviews.

@github-actions

Copy link
Copy Markdown

🔎 ol-dbt impact — column-level blast radius

✅ No column-level downstream impact detected for the changed models.

Posted by ol-dbt impact (annotate-only — does not block merge).

… reporting model

marts__combined_program_enrollment_detail computed program_completion_days as
start-minus-certificate (negative). program_enrollment_with_user_report
independently re-derived the same metric as program_complete_days with the
correct direction but re-parsed from the raw certificate timestamp string
instead of consuming the mart's field, creating two competing definitions.

Swap the date_diff operands in the mart to certificate-minus-start (positive,
matching both models' documented description), and have the reporting model
select enrollment_detail.program_completion_days directly instead of
re-deriving it from a differently-filtered join.

Part of #2375 (2026-07 dbt warehouse audit). Witan task: tk-reconcile-fifth-competing-metric-definition-prog-3160aa.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@blarghmatey blarghmatey force-pushed the worktree-program-completion-days-consolidate branch from 20ca5b7 to cdbc344 Compare July 13, 2026 15:32
Comment on lines 362 to 366
, date_diff(
'day'
, final_combined_programs.programcertificate_created_on_date
, final_combined_programs.first_courserun_start_on_date
, final_combined_programs.programcertificate_created_on_date
) as program_completion_days

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The direct call to date_diff() with swapped arguments will be correct for Trino (production) but will likely produce incorrect negative values in DuckDB (development/testing) due to differing implementations.
Severity: MEDIUM

Suggested Fix

Replace the native SQL call date_diff(...) with the dbt macro {{ date_diff(...) }}. The macro is designed to handle differences between database adapters like Trino and DuckDB, ensuring the calculation is consistent across all environments.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location:
src/ol_dbt/models/marts/combined/marts__combined_program_enrollment_detail.sql#L362-L366

Potential issue: The code was changed to use `date_diff('day',
first_courserun_start_on_date, programcertificate_created_on_date)` to calculate
`program_completion_days`. This direct call to the native SQL function, instead of the
provided `{{ date_diff(...) }}` dbt macro, will behave differently across database
systems. While this change corrects the calculation for the Trino production
environment, it will likely cause the calculation to be incorrect (producing a negative
value) in the DuckDB development environment, which has a different argument order for
its native `date_diff` function. This creates a divergence between development and
production environments for a core metric.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reconcile fifth competing metric definition: program_complete_days computed twice with opposite signs

2 participants